﻿module FunctionalAzure.Queue

open System
open System.IO
open System.Net
open System.Xml
open Microsoft.FSharp.Collections

open FunctionalAzure.Common

let table_host = "ipv4.fiddler:10001"

let string_to_sign (verb: string) content_encoding content_language content_length content_md5 content_type date if_modified_since if_match if_none_match if_unmodified_since range canonicalized_headers canonicalized_resource =
    String.Join("\n", 
        [|verb; content_encoding; content_language; content_length; content_md5; content_type; date; if_modified_since; if_match; if_none_match; if_unmodified_since; range; (canonicalized_headers + canonicalized_resource)|]
    )

let list_queues user key =
    let uri = "/devstoreaccount1?comp=list"
    let request_method = "GET"
    let request_path = String.Format("http://{0}{1}", table_host, uri)
    let current_date = System.DateTime.UtcNow.ToString("R", System.Globalization.CultureInfo.InvariantCulture)
    let contentMD5 = System.String.Empty
    let content_type = "application/atom+xml"
    let canonicalized_resource = canonicalize_resource user uri
    let ms_version = "2009-09-19"    
    let request : HttpWebRequest = downcast WebRequest.Create("http://" + table_host + uri)
    request.Method <- request_method
    request.ProtocolVersion <- (System.Version(1, 1))
    request.ContentType <- content_type
    request.Headers.Add("x-ms-date", current_date)
    request.Headers.Add("DataServiceVersion", "1.0;NetFx")
    request.Headers.Add("MaxDataServiceVersion", "1.0;NetFx")
    request.Headers.Add("Accept-Charset", "UTF-8")
    request.Headers.Add("x-ms-version", ms_version)
    let auth_header = get_authorization user key (string_to_sign request_method String.Empty String.Empty String.Empty String.Empty content_type String.Empty String.Empty String.Empty String.Empty String.Empty String.Empty (canonicalize_headers request.Headers) canonicalized_resource)
    request.Headers.Add("Authorization", auth_header)
    let response : HttpWebResponse = downcast request.GetResponse()
    let reader = new StreamReader(response.GetResponseStream())
    let data = reader.ReadToEnd()
    let doc = XmlDocument()
    doc.LoadXml(data)
    let nodes = doc.SelectNodes("/EnumerationResults/Queues/Queue/Name")
    [for i in nodes -> i.InnerText]

let create_queue user key queue_name = 
    let uri = "/devstoreaccount1/" + queue_name
    let request_method = "PUT"
    let request_path = String.Format("http://{0}{1}", table_host, uri)
    let current_date = System.DateTime.UtcNow.ToString("R", System.Globalization.CultureInfo.InvariantCulture)
    let contentMD5 = System.String.Empty
    let content_type = "application/atom+xml"
    let canonicalized_resource = canonicalize_resource user uri
    let ms_version = "2009-09-19"
    let content_length = 0    
    let request : HttpWebRequest = downcast WebRequest.Create("http://" + table_host + uri)
    request.Method <- request_method
    request.ProtocolVersion <- (System.Version(1, 1))
    request.ContentType <- content_type
    request.ContentLength <- int64 content_length
    request.Headers.Add("x-ms-date", current_date)
    request.Headers.Add("DataServiceVersion", "1.0;NetFx")
    request.Headers.Add("MaxDataServiceVersion", "1.0;NetFx")
    request.Headers.Add("Accept-Charset", "UTF-8")
    request.Headers.Add("x-ms-version", ms_version)
    let auth_header = get_authorization user key (string_to_sign request_method String.Empty String.Empty "0" String.Empty content_type String.Empty String.Empty String.Empty String.Empty String.Empty String.Empty (canonicalize_headers request.Headers) canonicalized_resource)
    request.Headers.Add("Authorization", auth_header)
    let response : HttpWebResponse = downcast request.GetResponse()
    let reader = new StreamReader(response.GetResponseStream())
    reader.ReadToEnd()

let get_message user key queue_name = 
    let uri = "/devstoreaccount1/" + queue_name + "/messages"
    let request_method = "GET"
    let request_path = String.Format("http://{0}{1}", table_host, uri)
    let current_date = System.DateTime.UtcNow.ToString("R", System.Globalization.CultureInfo.InvariantCulture)
    let contentMD5 = System.String.Empty
    let content_type = "application/atom+xml"
    let canonicalized_resource = canonicalize_resource user uri
    let ms_version = "2009-09-19"    
    let request : HttpWebRequest = downcast WebRequest.Create("http://" + table_host + uri)
    request.Method <- request_method
    request.ProtocolVersion <- (System.Version(1, 1))
    request.ContentType <- content_type
    request.Headers.Add("x-ms-date", current_date)
    request.Headers.Add("DataServiceVersion", "1.0;NetFx")
    request.Headers.Add("MaxDataServiceVersion", "1.0;NetFx")
    request.Headers.Add("Accept-Charset", "UTF-8")
    request.Headers.Add("x-ms-version", ms_version)
    let auth_header = get_authorization user key (string_to_sign request_method String.Empty String.Empty String.Empty String.Empty content_type String.Empty String.Empty String.Empty String.Empty String.Empty String.Empty (canonicalize_headers request.Headers) canonicalized_resource)
    request.Headers.Add("Authorization", auth_header)
    let response : HttpWebResponse = downcast request.GetResponse()
    let reader = new StreamReader(response.GetResponseStream())
    let data = reader.ReadToEnd()
    let doc = XmlDocument()
    doc.LoadXml(data)
    let nodes = doc.SelectNodes("/QueueMessagesList/QueueMessage")
    [for i in nodes -> (i.SelectSingleNode("MessageId").InnerText, i.SelectSingleNode("MessageText").InnerText, i.SelectSingleNode("PopReceipt").InnerText)]

let put_message user key queue_name message = 
    let uri = "/devstoreaccount1/" + queue_name + "/messages"
    let request_method = "POST"
    let request_path = String.Format("http://{0}{1}", table_host, uri)
    let current_date = System.DateTime.UtcNow.ToString("R", System.Globalization.CultureInfo.InvariantCulture)
    let contentMD5 = System.String.Empty
    let content_type = "application/atom+xml"
    let canonicalized_resource = canonicalize_resource user uri
    let ms_version = "2009-09-19"    
    let request : HttpWebRequest = downcast WebRequest.Create("http://" + table_host + uri)
    request.Method <- request_method
    request.ProtocolVersion <- (System.Version(1, 1))
    request.ContentType <- content_type
    request.Headers.Add("x-ms-date", current_date)
    request.Headers.Add("DataServiceVersion", "1.0;NetFx")
    request.Headers.Add("MaxDataServiceVersion", "1.0;NetFx")
    request.Headers.Add("Accept-Charset", "UTF-8")
    request.Headers.Add("x-ms-version", ms_version)
    let content = String.Format("<QueueMessage><MessageText>{0}</MessageText></QueueMessage>", box message)
    request.ContentLength <- int64 content.Length
    let auth_header = get_authorization user key (string_to_sign request_method String.Empty String.Empty (content.Length.ToString()) String.Empty content_type String.Empty String.Empty String.Empty String.Empty String.Empty String.Empty (canonicalize_headers request.Headers) canonicalized_resource)
    request.Headers.Add("Authorization", auth_header)
    let writer = new StreamWriter(request.GetRequestStream())
    writer.Write(content)
    writer.Flush()
    let response : HttpWebResponse = downcast request.GetResponse()
    let reader = new StreamReader(response.GetResponseStream())
    reader.ReadToEnd() |> ignore
    true

let delete_message user key queue_name id pop_reciept =
    let uri = "/devstoreaccount1/" + queue_name + "/messages/" + id + "?popreceipt=" + pop_reciept
    let request_method = "DELETE"
    let request_path = String.Format("http://{0}{1}", table_host, uri)
    let current_date = System.DateTime.UtcNow.ToString("R", System.Globalization.CultureInfo.InvariantCulture)
    let contentMD5 = System.String.Empty
    let content_type = "application/atom+xml"
    let canonicalized_resource = canonicalize_resource user uri
    let ms_version = "2009-09-19"    
    let request : HttpWebRequest = downcast WebRequest.Create("http://" + table_host + uri)
    request.Method <- request_method
    request.ProtocolVersion <- (System.Version(1, 1))
    request.ContentType <- content_type
    request.Headers.Add("x-ms-date", current_date)
    request.Headers.Add("DataServiceVersion", "1.0;NetFx")
    request.Headers.Add("MaxDataServiceVersion", "1.0;NetFx")
    request.Headers.Add("Accept-Charset", "UTF-8")
    request.Headers.Add("x-ms-version", ms_version)
    let auth_header = get_authorization user key (string_to_sign request_method String.Empty String.Empty String.Empty String.Empty content_type String.Empty String.Empty String.Empty String.Empty String.Empty String.Empty (canonicalize_headers request.Headers) canonicalized_resource)
    request.Headers.Add("Authorization", auth_header)
    let response : HttpWebResponse = downcast request.GetResponse()
    let reader = new StreamReader(response.GetResponseStream())
    printfn "%A" (reader.ReadToEnd())